#pragma once 

#include <iostream>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <functional>
#include <pthread.h>


std::string GetPthreadName()
{
    static int num = 1;
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "Thread-%d", num);
    num++;

    return buffer;
}   

template<class Return, class Parameter>
using func_t = std::function<Return(Parameter)>;

template<class Return, class Parameter>
class Thread
{
public:
    static void* PthreadRoutine(void* argv)
    {
        if (argv == nullptr)
            return nullptr;

        Thread* ts = static_cast<Thread*>(argv);
        ts->_func(ts->_mes);

        return nullptr;
    }

    Thread(func_t<Return, Parameter> func, Parameter mes, std::string name = "")
        : _func(func)
        , _isruning(false)
        , _mes(mes)
    {
        if (name.empty())
        {
            _name = GetPthreadName();
        }
        else 
        {
            _name = name;
        }
    }

    void Create()
    {
        int n = pthread_create(&_pthread, nullptr, PthreadRoutine, this);
        if (n < 0)
        {
            std::cerr << "线程创建失败  [errno: " << errno << "  strerror: " << strerror(errno) << "]" << std::endl;
            return;
        }
        _isruning = true;
    }

    void Jion()
    {
        int n = pthread_join(_pthread, nullptr);
        if (n < 0)
        {
            std::cerr << "线程等待失败  [errno: " << errno << "  strerror: " << strerror(errno) << "]" << std::endl;
            return;
        }
        _isruning = false;
    }

    bool IsRuning()
    {
        return _isruning;
    }

    std::string ThreadName()
    {
        return _name;
    }

private:
    pthread_t _pthread;
    func_t<Return, Parameter> _func;
    std::string _name;
    Parameter _mes;
    bool _isruning;
};